package com.reliable.service.serviceimpl;

import com.reliable.api.dto.ReliableTransactionRecord.RiskTransactionDTO;
import com.reliable.api.dto.excel.ReliableTransactionExportExcel;
import com.reliable.api.dto.transaction.BankCardTransactionDTO;
import com.reliable.common.annotation.DataSource;
import com.reliable.common.core.domain.AjaxResult;
import com.reliable.common.enums.DataSourceType;
import com.reliable.service.domain.ReliableExportRecord;
import com.reliable.service.domain.ReliableExportPushRecord;
import com.reliable.service.domain.ReliablePushTemplate;
import com.reliable.service.domain.ReliableTransactionRecord;
import com.reliable.service.mapper.ReliableExportRecordMapper;
import com.reliable.service.mapper.ReliableTransactionRecordMapper;
import com.reliable.service.mapper.ReliableExportPushRecordMapper;
import com.reliable.service.oss.service.OssService;
import com.reliable.service.service.IReliablePushTemplateService;
import com.reliable.service.service.IReliableTransactionRecordService;
import com.reliable.service.utils.SftpUploader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

@Service
@DataSource(value = DataSourceType.MASTER)
public class ReliableTransactionRecordServiceImpl
    extends ServiceImpl<ReliableTransactionRecordMapper, ReliableTransactionRecord>
    implements IReliableTransactionRecordService {

    private final ReliableTransactionRecordMapper reliableTransactionRecordMapper;

    private final ReliableExportRecordMapper exportRecordMapper;
    
    private final ReliableExportPushRecordMapper exportPushRecordMapper;

    @Autowired
    private IReliablePushTemplateService pushTemplateService;

    @Autowired
    private SftpUploader sftpUploader;

    @Autowired
    private OssService ossService;

    public ReliableTransactionRecordServiceImpl(ReliableTransactionRecordMapper reliableTransactionRecordMapper, 
                                               ReliableExportRecordMapper exportRecordMapper,
                                               ReliableExportPushRecordMapper exportPushRecordMapper) {
        this.reliableTransactionRecordMapper = reliableTransactionRecordMapper;
        this.exportRecordMapper = exportRecordMapper;
        this.exportPushRecordMapper = exportPushRecordMapper;
    }


    /**
     * 将银行卡信息导出到本地文件
     * @return 导出结果
     */
    public AjaxResult exportBankCardsToLocal(String param) {
        long temId = Long.parseLong(param);

        ReliablePushTemplate pushTemplate = pushTemplateService.getById(temId);
        if (pushTemplate == null) {
            return AjaxResult.error("交易记录不存在");
        }
        if (pushTemplate.getTemplateStatus() == 2) {
            return AjaxResult.error("交易记录已禁用");
        }


        // 创建推送记录
        ReliableExportPushRecord pushRecord = new ReliableExportPushRecord();
        pushRecord.setChannel(pushTemplate.getChannel());
        pushRecord.setCity(pushTemplate.getCity());
        pushRecord.setDepartment(pushTemplate.getDepartment());
        pushRecord.setPushStatus(1); // 处理中
        pushRecord.setPushTime(new Date());
        pushRecord.setRetryCount(0);
        pushRecord.setRecordCount(0);
        exportPushRecordMapper.insert(pushRecord);

        File tempFile = null; // 用于 finally 中删除

        try {
            System.out.println("开始执行exportBankCardsToLocal方法，时间：" + new java.util.Date());
            String exportType = "bank_card";
            ReliableExportRecord record = exportRecordMapper.selectByType(exportType, temId);
            Date lastExportTime = record != null && record.getLastExportTime() != null
                    ? record.getLastExportTime()
                    : new Date(0);

            // 随机导出180-230条数据
            int minCount = 180;
            int maxCount = 230;
            int randomCount = ThreadLocalRandom.current().nextInt(maxCount - minCount + 1) + minCount;

            List<ReliableTransactionExportExcel> records = reliableTransactionRecordMapper.exportRandomBankCardsAfter(lastExportTime, 0, randomCount);
            System.out.println("查询到 " + records.size() + " 条银行卡数据，本次随机导出数量:" + randomCount);

            pushRecord.setRecordCount(records.size());
            exportPushRecordMapper.updateById(pushRecord);

            if (records.isEmpty()) {
                pushRecord.setPushStatus(2); // 成功
                exportPushRecordMapper.updateById(pushRecord);
                return AjaxResult.success("无新数据，无需导出");
            }

            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHH");
            String timestamp = sdf.format(new Date());
            String localFilePath = "D:/reliable1/data_to_cy_" + timestamp + ".csv";
            String remoteFileName = "data_to_cy_" + timestamp + ".csv";

            tempFile = new File(localFilePath);
            tempFile.getParentFile().mkdirs();

            // 写入 CSV 文件
            try (OutputStream out = new FileOutputStream(tempFile)) {
                out.write(new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF}); // UTF-8 BOM

                SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                for (ReliableTransactionExportExcel item : records) {
                    String accountIdentifier = Optional.ofNullable(item.getAccountIdentifier()).orElse("");
                    String paymentPlatformName = Optional.ofNullable(item.getPlatformName()).orElse("");
                    String victimName = Optional.ofNullable(item.getVictimName()).orElse("");
                    String idNumber = Optional.ofNullable(item.getIdNumber()).orElse("");
                    String phoneNumber = Optional.ofNullable(item.getPhoneNumber()).orElse("");
                    String warningTime = item.getCreateTime() != null ? sdf1.format(item.getCreateTime()) : "";

                    String line = String.format("%s,%s,%s,%s,%s,%s\n",
                            escapeCsvField(accountIdentifier),
                            escapeCsvField(paymentPlatformName),
                            escapeCsvField(victimName),
                            escapeCsvField(idNumber),
                            escapeCsvField(phoneNumber),
                            escapeCsvField(warningTime)
                    );
                    out.write(line.getBytes(StandardCharsets.UTF_8));
                }
            }

            // 计算最新导出时间
            Date newExportTime = records.stream()
                    .map(ReliableTransactionExportExcel::getCreateTime)
                    .filter(Objects::nonNull)
                    .max(Comparator.comparing(Date::getTime))
                    .orElse(new Date());

            // 1. 上传到 SFTP
            sftpUploader.upload(tempFile, remoteFileName);

            // 2. 上传到 OSS 做留存
            String ossUrl =ossService.uploadFile(tempFile);

            // 3. 更新导出记录（filePath 存 OSS URL）
            if (record == null) {
                record = new ReliableExportRecord();
                record.setExportType(exportType);
                record.setLastExportTime(newExportTime);
                record.setFilePath(ossUrl); // 存 OSS 地址作为留存
                record.setTemId(temId);
                exportRecordMapper.insert(record);
            } else {
                record.setLastExportTime(newExportTime);
                record.setFilePath(ossUrl);
                exportRecordMapper.updateByType(record);
            }

            // 4. 更新推送记录
            pushRecord.setPushStatus(2); // 成功
            pushRecord.setFilePath(ossUrl); // 推送记录也存 OSS 地址（或可存两个字段）
            pushRecord.setExportRecordId(record.getId());
            exportPushRecordMapper.updateById(pushRecord);

            System.out.println("导出银行卡数据完成，OSS留存地址：" + ossUrl);
            return AjaxResult.success(
                    "导出成功，已推送至SFTP: " + remoteFileName +
                            "，留存文件: " + ossUrl +
                            "，导出数据量：" + records.size()
            );

        } catch (Exception e) {
            System.err.println("导出银行卡数据失败: " + e.getMessage());
            e.printStackTrace();

            pushRecord.setPushStatus(3); // 失败
            pushRecord.setErrorMessage(e.getMessage());
            exportPushRecordMapper.updateById(pushRecord);

            return AjaxResult.error("导出失败: " + e.getMessage());
        } finally {
            // 尝试删除临时本地文件（无论成功失败）
            if (tempFile != null && tempFile.exists()) {
                boolean deleted = tempFile.delete();
                if (!deleted) {
                    System.err.println("警告：临时文件删除失败: " + tempFile.getAbsolutePath());
                }
            }
        }
    }

    // 标准 CSV 转义方法（无零宽空格！）
    private static String escapeCsvField(String value) {
        if (value == null) {
            return "";
        }
        // 如果字段包含特殊字符，则用双引号包裹，并转义内部双引号
        if (value.contains(",") || value.contains("\n") || value.contains("\r") || value.contains("\"")) {
            return "\"" + value.replace("\"", "\"\"") + "\"";
        }
        return value;
    }
    
    @Override
    public Map<String, Object> getTransactionStatistics() {
        Map<String, Object> result = new HashMap<>();
        
        // 总交易数
        long totalCount = this.count();
        result.put("totalCount", totalCount);
        
        // 今日交易数
        LocalDateTime todayStart = LocalDate.now().atStartOfDay();
        LocalDateTime todayEnd = LocalDate.now().atTime(LocalTime.MAX);
        com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ReliableTransactionRecord> todayWrapper = new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>();
        todayWrapper.between(ReliableTransactionRecord::getCreateTime, todayStart, todayEnd);
        long todayCount = this.count(todayWrapper);
        result.put("todayCount", todayCount);
        
        // 昨日交易数
        LocalDateTime yesterdayStart = LocalDate.now().minusDays(1).atStartOfDay();
        LocalDateTime yesterdayEnd = LocalDate.now().minusDays(1).atTime(LocalTime.MAX);
        com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ReliableTransactionRecord> yesterdayWrapper = new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>();
        yesterdayWrapper.between(ReliableTransactionRecord::getCreateTime, yesterdayStart, yesterdayEnd);
        long yesterdayCount = this.count(yesterdayWrapper);
        result.put("yesterdayCount", yesterdayCount);
        
        return result;
    }
    
    @Override
    public List<RiskTransactionDTO> getRiskTransactions() {
        return reliableTransactionRecordMapper.selectRiskTransactions();
    }

    /**
     * 分页查询银行卡交易记录
     *
     * @param accountIdentifier 银行卡号（模糊查询）
     * @param platformName      平台名称（模糊查询）
     * @param pageNum           页码
     * @param pageSize          页面大小
     * @return 银行卡交易记录列表
     */
    @Override
    public List<BankCardTransactionDTO> selectBankCardTransactions(String accountIdentifier, String platformName, int pageNum, int pageSize) {
        int offset = (pageNum - 1) * pageSize;
        return reliableTransactionRecordMapper.selectBankCardTransactions(accountIdentifier, platformName, offset, pageSize);
    }
}